﻿using Microsoft.SharePoint;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace WindStyle.SPEntity.Converters
{
    public class SPFieldUrlValueConverter : IValueConverter
    {
        public object ToFieldValue(object value, Type targetType, ConversionContext context)
        {
            if (context.Attribute is Attributes.UrlFieldAttribute)
            {
                var attribute = context.Attribute as Attributes.UrlFieldAttribute;
                var type = value.GetType();

                object url;
                try
                {
                    url = type.GetProperty(attribute.UrlProperty).GetValue(value, null);
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format("Convert Url failed, cannot find property [{0}].",
                        attribute.UrlProperty),
                        e);
                }

                string description = string.Empty;
                try
                {
                    var result = type.GetProperty(attribute.DescriptionProperty).GetValue(value, null);
                    if (result != null)
                        description = result.ToString();
                }
                catch (Exception e)
                {
                    throw new ArgumentException(string.Format("Convert Description failed, cannot find property [{0}].",
                        attribute.DescriptionProperty),
                        e);
                }

                var field = new SPFieldUrlValue();
                field.Description = description;
                if (url is Uri)
                    field.Url = (url as Uri).OriginalString;
                else
                    field.Url = url as string;
                return field;
            }
            else if (value is string)
                return new SPFieldUrlValue(value as string);
            return null;
        }

        public object ToPropertyValue(object value, Type targetType, ConversionContext context)
        {
            SPFieldUrlValue fieldValue = null;
            if (value is SPFieldUrlValue)
                fieldValue = value as SPFieldUrlValue;
            else if (value is string)
                fieldValue = new SPFieldUrlValue(value as string);

            if (fieldValue == null)
                return null;

            if (context.Attribute is Attributes.UrlFieldAttribute)
            {
                var urlAttribute = context.Attribute as Attributes.UrlFieldAttribute;
                if (urlAttribute.ValuePart == Attributes.UrlValue.Url)
                {
                    if (targetType == typeof(Uri))
                        return new Uri(fieldValue.Url);
                    else
                        return Convert.ChangeType(fieldValue.Url, targetType);
                }
                else if (urlAttribute.ValuePart == Attributes.UrlValue.Description)
                {
                    return Convert.ChangeType(fieldValue.Description, targetType);
                }
                else
                {
                    var result = Activator.CreateInstance(targetType);
                    try
                    {
                        var urlProperty = targetType.GetProperty(urlAttribute.UrlProperty);
                        var url = System.Convert.ChangeType(fieldValue.Url, urlProperty.PropertyType);
                        urlProperty.SetValue(result, url, null);
                    }
                    catch (Exception e)
                    {
                        throw new ArgumentException(string.Format("Convert Url failed, cannot find property [{0}] or the value [{1}] cannot be converted to the type of that property.",
                            urlAttribute.UrlProperty,
                            fieldValue.Url), e);
                    }

                    try
                    {
                        var descriptionProperty = targetType.GetProperty(urlAttribute.DescriptionProperty);
                        var description = System.Convert.ChangeType(fieldValue.Description, descriptionProperty.PropertyType);
                        descriptionProperty.SetValue(result, description, null);
                    }
                    catch (Exception e)
                    {
                        throw new ArgumentException(string.Format("Convert Description failed, cannot find property [{0}] or the value [{1}] cannot be converted to the type of that property.",
                            urlAttribute.DescriptionProperty,
                            fieldValue.Description), e);
                    }
                    return result;
                }
            }
            else if (targetType == typeof(string))
                return fieldValue.ToString();

            return null;
        }
    }
}
